﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace 综合同步
{
    class TcmsComRev<T>
    {
        bool m_bStopSerial = false;
        SerialPort m_serialPort;
        Stopwatch m_TimeWatch = new Stopwatch();  
        ConcurrentQueue<TcmsData> m_TcmsPackageQueue = new ConcurrentQueue<TcmsData>();

        #region 属性
        TcmsData m_tcms;
        public TcmsData NowTcms 
        { 
            get { lock (this) return m_tcms; }
            set { lock (this) m_tcms = value; }
        }
        #endregion

        public TcmsComRev(string com)
        {
            typeof(T).InvokeMember("TcmsCommand", BindingFlags.Static | BindingFlags.Public | 
                BindingFlags.InvokeMethod, null, null, new object[]{m_TcmsPackageQueue});
            //接收tcms信号
            Task.Run(new Action(() =>
            {
                try
                {
                    m_serialPort = new SerialPort(com);
                    m_serialPort.ReadTimeout = 1000;
                    m_serialPort.Open();

                    //启动接收
                    bool bSerialTimeOut = false;
                    int writeIndex = 0,readIndex = 0;
                    byte[] tcmsBuf = new byte[Marshal.SizeOf(typeof(T)) * 2];
                    FileLogOperator.Info("TCMS连接成功");
                    while(!m_bStopSerial)
                    {
                        try
                        {
                            if (!m_serialPort.IsOpen)
                                m_serialPort.Open();

                            int len = 0;
                            m_TimeWatch.Restart();//重新计数
                            writeIndex %= tcmsBuf.Length;
                            readIndex %= tcmsBuf.Length;
                            if(writeIndex>=readIndex){
                                len = m_serialPort.Read(tcmsBuf, writeIndex,tcmsBuf.Length-writeIndex);
                            }
                            else{
                                len = m_serialPort.Read(tcmsBuf, writeIndex,readIndex-writeIndex);
                            }
                            writeIndex += len;
                            if(len==0)  {
                                Thread.Sleep(1);
                                continue;
                            }
                            if(m_TimeWatch.ElapsedMilliseconds > 300)
                            {
                                string tcmsReceiveError = "TCMS接收数据间隔"+ m_TimeWatch.ElapsedMilliseconds + "ms";
                                FileLogOperator.Error(tcmsReceiveError);
                            }
                            //Console.WriteLine(writeIndex+"-"+readIndex+"-"+len+":"+string.Join(" ", tcmsBuf.Skip(writeIndex-len).Take(len).Select(t => t.ToString("X2"))));
                            #region 缓存数据
                            if (LocalServer.instance().m_bSaveData)
                            {
                                try
                                {
                                    if (!Directory.Exists("tcmsLog")) Directory.CreateDirectory("tcmsLog");
                                    File.AppendAllText("tcmsLog" + DateTime.Now.ToString("yyyyMMdd") + ".log",
                                        DateTime.Now.ToString() + "       " + string.Join(" ", tcmsBuf.Skip(writeIndex-len).Take(len).Select(t => t.ToString("X2"))) + "\r\n");
                                }
                                catch (Exception)
                                {
                                    File.AppendAllText("tcmsLog" + DateTime.Now.ToString("yyyyMMdd") + ".log",
                                        DateTime.Now.ToString() + "【Error】" + string.Join(" ", tcmsBuf.Skip(writeIndex-len).Take(len).Select(t => t.ToString("X2"))) + "\r\n");
                                }
                            }
                            #endregion

                            object[] args = new object[] { tcmsBuf, writeIndex, readIndex, m_TcmsPackageQueue };
                            typeof(T).InvokeMember("ParseData", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, args);
                            readIndex = (int)args[2];
                            bSerialTimeOut = false;
                        }
                        catch(TimeoutException)
                        {
                            if(!bSerialTimeOut)
                                FileLogOperator.Info("TCMS接收数据超时,请检查连接");
                            bSerialTimeOut = true;
                        }
                        catch(Exception ex)
                        {
                            FileLogOperator.Error(ex.Message);
                        }
                    }
                }
                catch (Exception ex)
                {
                    FileLogOperator.Error(ex.Message);
                }
            }));
        }
        ~TcmsComRev()
        {
            m_bStopSerial = true;
            if (m_serialPort != null)
                m_serialPort.Close();
        }
    }
}
